package com.zb.frame.modules.common.controller;

import com.zb.frame.base.config.shiro.SelfToken;
import com.zb.frame.base.exception.SelfDefineException;
import com.zb.frame.base.model.R;
import com.zb.frame.base.utils.JWTUtil;
import com.zb.frame.base.utils.encrypt.SimpleHashUtil;
import com.zb.frame.modules.common.vo.LoginForm;
import com.zb.frame.modules.common.vo.UserInfoVO;
import com.zb.frame.modules.monitor.enums.LogModule;
import com.zb.frame.modules.monitor.enums.LogType;
import com.zb.frame.modules.monitor.service.LogService;
import com.zb.frame.modules.sys.entity.User;
import com.zb.frame.modules.common.entity.UserToken;
import com.zb.frame.modules.sys.service.UserService;
import com.zb.frame.modules.common.service.UserTokenService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/login")
public class LoginController {

    @Autowired
    UserService userService;

    @Autowired
    UserTokenService userTokenService;

    @Autowired
    LogService logService;

    @Value("${zb.config.jwt.token.defaultExpired}")
    private int accessExpired;

    /**
     * 登录接口
     * @param loginForm 登录表单数据
     * @return {"access_token":"XXX","refresh_token":"XXX","userInfo":{"alias":"XXX","avatar":"XXX"}}
     */
    @PostMapping("/auth")
    public R doLogin(@RequestBody LoginForm loginForm) {
        String username = loginForm.getUsername();
        String password = loginForm.getPassword();
        // 此处验证验证码，有两种方法 1.可以存入session（做无状态的不建议） 2.可以数据库建表存入code和过期时间
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new SelfDefineException(401, "登录失败，用户不存在！");
        }
        if (user.getUserStatus() == 0) {
            throw new SelfDefineException(401, "登录失败，用户已被禁用，请联系管理员！");
        }
        if (user.getUserStatus() == 2) {
            throw new SelfDefineException(401, "登录失败，用户被锁定，请联系管理员！");
        }
        if (!user.getUserPassword().equals(SimpleHashUtil.encode(password))){
            throw new SelfDefineException(401, "登录失败，用户密码错误！");
        }
        String accessToken = JWTUtil.generatorToken(String.valueOf(user.getUserId()), accessExpired);
        SelfToken jwtToken = new SelfToken(accessToken);
        Subject subject = SecurityUtils.getSubject();
        subject.login(jwtToken);
        // 返回数据
        Map<String, Object> returnData = new HashMap<>();
        UserInfoVO userInfo = new UserInfoVO();
        userInfo.setAlias(user.getUserAlias());
        userInfo.setAvatar(user.getUserAvatar());
        returnData.put("userInfo",userInfo);
        returnData.put("access_token", accessToken);
        String refreshToken = userTokenService.newUserToken(user.getUserId());
        returnData.put("refresh_token", refreshToken);
        // 登录成功，添加日志
        logService.addLog(LogModule.BASEMODULE, LogType.LOGIN,"","",String.valueOf(user.getUserId()),user.getUserId(),"用户[" + user.getUserName() + "][" + user.getUserAlias() + "]登录成功");
        return R.ok("登录成功！", returnData);
    }

    /**
     * access_token过期 刷新
     * @return {"access_token":"XXX","refresh_token":"XXX"}
     */
    @GetMapping("/refresh")
    public R doRefresh(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        // System.out.println("doRefresh---token----" + token);
        UserToken tokenInfo = userTokenService.getUserTokenByToken(token);
        if (tokenInfo == null) {
            return R.error(404,"","token不存在!");
        } else if(tokenInfo.getExpiredTime().getTime() < System.currentTimeMillis()) {
            return R.error(401,"","token已过期，请重新登录!");
        } else {
            Map<String, Object> returnData = new HashMap<>();
            String accessToken = JWTUtil.generatorToken(String.valueOf(tokenInfo.getUserId()), accessExpired);
            String refreshToken = userTokenService.newUserToken(tokenInfo.getUserId());
            returnData.put("accessToken", accessToken);
            returnData.put("refreshToken", refreshToken);
            return R.ok(returnData);
        }
    }

}
